home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / demos / 108 / modula / makemake.mod < prev    next >
Encoding:
Text File  |  1987-02-20  |  9.5 KB  |  292 lines

  1. MODULE MakeMake;
  2.  
  3.   (*
  4.    * MAKEMAKE.  Create a MAKEFILE for a MODULA-2 program.
  5.    *
  6.    * Written by Steve Tynor, 30 September 1986.
  7.    *            UUCP  : tynor@gitpyr
  8.    *            USNAIL: 2550 Akers Mill Rd. T-2, Atlanta GA. 30339
  9.    *
  10.    * Permission is granted to distribute, copy and change this program as long
  11.    * as this notice remains...
  12.    *)
  13.  
  14.   (*
  15.    * MAKEMAKE.  Create a MAKEFILE for a MODULA-2 program.
  16.    * Usage:
  17.    *      MAKEMAKE "main-module-modulename"
  18.    *
  19.    *    Even though module dependencies are explicit in MODULA-2, it can still
  20.    * be quite a chore to figure them out and create a MAKEFILE.  This program 
  21.    * reads the text file associated with the module name given on the command 
  22.    * line and recursively checks dependencies for all imported files.  It then
  23.    * creates a MAKEFILE suitable for use with the Unix MAKE utility.  If a 
  24.    * file is not found and is not a recognized library module, then the
  25.    * MAKEFILE will include a comment:
  26.    *     ## File NOT Found ##
  27.    * on the right hand side of the dependency.
  28.    *
  29.    *
  30.    * This program was written on the Atari ST using TDI Modula-2. 
  31.    *
  32.    * BUGS:
  33.    *     the CommandLine module dies when a null command line is seen.  
  34.    * Unfortunately, I no longer have the source to the module, so I can't
  35.    * fix it.  This bug also seems to consider a command line consisting of
  36.    * a single character as a reason for dieing.
  37.    *
  38.    * Suggestions for porting to another compiler:
  39.    *
  40.    *    1) module CommandLine is non-standard.  It exports 2 procedures:
  41.    *          PROCEDURE GetArgument (    num      : CARDINAL; 
  42.    *                                 VAR filename : ARRAY OF CHAR);
  43.    *          PROCEDURE NumberOfArguments() : CARDINAL;
  44.    *       they do just what their names imply. (ie. like C's argv, argc)
  45.    *
  46.    *    2) the IMPLEMENTATION MODULE MakeLibraries will have to be edited to
  47.    *       reflect the standard library that your compiler knows about.  List
  48.    *       any modules that you don't want included in your MAKEFILE.  Library
  49.    *       modules are listed in the MAKEFILE, but are commented out.
  50.    *
  51.    *    3) the procedure ModulenameToFilename in MakeParse will have to be
  52.    *       modified so that it creates the correct filename for your machine.
  53.    *
  54.    *    4) if your MAKE program has default MODULA-2 rules, set the constant
  55.    *       MAKEHasModulaRules (in this module) to TRUE.  This will prevent
  56.    *       MAKEMAKE from producing remake lines. 
  57.    *    
  58.    *    5) the procedure WriteFilename takes a parameter: extension.  Trace
  59.    *       all the calls to this function and make sure the proper extentions
  60.    *       are used.  in TDI Modula, '.DEF' = definition module text
  61.    *                                 '.MOD' = implementation module text
  62.    *                                 '.SYM' = symbol file (compiled DEF)
  63.    *                                 '.LNK' = symbol file (compiled MOD)
  64.    *)
  65.  
  66. IMPORT InOut;
  67. IMPORT CommandLine;
  68. IMPORT MakeForest;
  69. IMPORT MakeParse;
  70. IMPORT ASCII;
  71. IMPORT Streams;
  72. IMPORT Strings;
  73.  
  74. CONST
  75.   MAKEHasModulaRules = FALSE;
  76.   CompilerPathname   = 'C:\BIN\MOD.PRG ';
  77.   LinkerPathname     = 'C:\BIN\LNK.PRG ';
  78.  
  79. VAR
  80.   outputStream : Streams.Stream;
  81.  
  82.   (*----------------------------------------------------------------------*)
  83.   PROCEDURE CloseOutput;
  84.   VAR
  85.     reply : INTEGER;
  86.   BEGIN
  87.     Streams.CloseStream (outputStream, reply);
  88.   END CloseOutput;
  89.  
  90.   (*----------------------------------------------------------------------*)
  91.   PROCEDURE OpenOutput (VAR filename : ARRAY OF CHAR) : BOOLEAN;
  92.   VAR
  93.     reply : INTEGER;
  94.   BEGIN
  95.     Streams.OpenStream (outputStream, filename, Streams.READWRITE, reply);
  96.     RETURN reply = 0;
  97.   END OpenOutput;
  98.  
  99.  
  100.   (*----------------------------------------------------------------------*)
  101.   PROCEDURE Write (ch : CHAR);
  102.   BEGIN
  103.     Streams.Write8Bit (outputStream, ch);
  104.   END Write;
  105.  
  106.  
  107.   (*----------------------------------------------------------------------*)
  108.   PROCEDURE WriteString (VAR str : ARRAY OF CHAR);
  109.   VAR
  110.     c : CARDINAL;
  111.   BEGIN
  112.     c := 0;
  113.     WHILE (c <= HIGH(str)) AND (str[c] <> 0C) DO
  114.       Write(str[c]);
  115.       INC(c);
  116.     END; (* WHILE *)
  117.   END WriteString;
  118.  
  119.  
  120.   (*----------------------------------------------------------------------*)
  121.   PROCEDURE WriteLn;
  122.   BEGIN
  123.     Write ( ASCII.CR );
  124.     Write ( ASCII.LF );
  125.   END WriteLn;
  126.  
  127.  
  128.   (*----------------------------------------------------------------------*)
  129.   PROCEDURE WriteMakefile;
  130.  
  131.     (*--------------------------------------------------------------------*)
  132.      PROCEDURE WriteFileDependency (file : MakeForest.FileDefinitionList;
  133.                                     VAR lhsExtention : ARRAY OF CHAR);
  134.      VAR
  135.        c    : CARDINAL;
  136.        iptr : MakeForest.ImportList;
  137.      BEGIN
  138.        IF file <> NIL THEN
  139.          IF file^.filename[0] = '#' THEN
  140.            RETURN;
  141.          END; (* IF *) 
  142.          WriteFilename (file^.filename, lhsExtention);
  143.          Write (ASCII.HT);
  144.          WriteString (': ');
  145.          WriteString (file^.filename);
  146.            (* if this is a .LNK file, then don't forget the .SYM file: *)
  147.            (* but don't do it for the main module! *)
  148.          IF (file <> MakeForest.FileForestEnd) AND
  149.             (Strings.Compare (lhsExtention, '.LNK') = Strings.Equal) THEN
  150.            Write (' ');
  151.            WriteFilename (file^.filename, '.SYM');
  152.            c := 3;
  153.          ELSE
  154.            c := 2;
  155.          END; (* IF *)
  156.          iptr := file^.imports;
  157.          WHILE iptr <> NIL DO
  158.            IF NOT iptr^.file^.library THEN
  159.              IF c > 4 THEN
  160.                WriteString (' \');
  161.                WriteLn;
  162.                WriteString ('  ');
  163.                c := 0;
  164.              END; (* IF *)
  165.              Write (' ');
  166.              WriteFilename (iptr^.file^.filename, '.SYM'); 
  167.              INC (c);
  168.            END; (* IF *)
  169.            iptr := iptr^.next;
  170.          END; (* WHILE *)
  171.  
  172.          iptr := file^.imports;
  173.          c := 5;  (* <-- force a WriteLn *)
  174.          WHILE iptr <> NIL DO
  175.            IF iptr^.file^.library THEN
  176.              IF c > 4 THEN
  177.                WriteLn;
  178.                WriteString ('  #libs:  ');
  179.                c := 0;
  180.              END; (* IF *)
  181.              Write (' ');
  182.              WriteFilename (iptr^.file^.filename, '.SYM'); 
  183.              INC (c);
  184.            END; (* IF *)
  185.            iptr := iptr^.next;
  186.          END; (* WHILE *)
  187.  
  188.          WriteLn;
  189.          IF NOT MAKEHasModulaRules THEN
  190.            Write (ASCII.HT);
  191.            WriteString (CompilerPathname);
  192.            WriteString (file^.filename);
  193.            WriteLn;
  194.          END; (* IF *)
  195.        END; (* IF *)
  196.      END WriteFileDependency;
  197.  
  198.     (*--------------------------------------------------------------------*)
  199.     PROCEDURE WriteAllLnkFiles;
  200.     VAR
  201.       c, dummy    : CARDINAL;
  202.       ptr : MakeForest.FileDefinitionList;
  203.     BEGIN
  204.       ptr := MakeForest.FileForest;
  205.       c := 2;
  206.       REPEAT
  207.         IF Strings.Pos (ptr^.filename, '.MOD', 0, dummy) THEN
  208.           IF NOT ptr^.library THEN
  209.             WriteFilename (ptr^.filename, '.LNK');  
  210.             Write (' ');
  211.             IF c > 4 THEN
  212.               WriteString (' \');
  213.               WriteLn;
  214.               WriteString ('  ');
  215.               c := 0;
  216.             END; (* IF *)
  217.             INC (c);
  218.           END; (* IF *)
  219.         END; (* IF *)
  220.         ptr := ptr^.next;
  221.       UNTIL ptr = NIL;
  222.       WriteLn;
  223.     END WriteAllLnkFiles;
  224.  
  225.     (*--------------------------------------------------------------------*)
  226.     PROCEDURE WriteFilename (VAR filename, extention : ARRAY OF CHAR);
  227.     VAR
  228.       c : CARDINAL;
  229.     BEGIN
  230.       c := 0;
  231.       REPEAT
  232.         Write (filename[c]);
  233.         INC(c);
  234.       UNTIL (c > HIGH (filename)) OR (filename[c] = '.');
  235.       WriteString (extention);
  236.     END WriteFilename;
  237.  
  238.     (*--------------------------------------------------------------------*)
  239.     PROCEDURE WritePRGDependency (file : MakeForest.FileDefinitionList);
  240.     BEGIN
  241.       WriteLn;
  242.       WriteFilename (file^.filename, '.PRG');
  243.       Write (ASCII.HT);  WriteString (': ');
  244.       WriteAllLnkFiles;
  245.       IF NOT MAKEHasModulaRules THEN
  246.         Write (ASCII.HT);  WriteString (LinkerPathname);
  247.         WriteFilename (file^.filename, '.LNK');
  248.         WriteLn;
  249.       END; (* IF *)
  250.     END WritePRGDependency;
  251.  
  252.   VAR
  253.     ptr    : MakeForest.FileDefinitionList;
  254.     c      : CARDINAL;
  255.   BEGIN
  256.     IF OpenOutput ('MAKEFILE') THEN
  257.         (* print out the .PRG dependency first.... *)
  258.       WritePRGDependency (MakeForest.FileForestEnd);
  259.       WriteFileDependency (MakeForest.FileForestEnd, '.LNK');
  260.       ptr := MakeForest.FileForest;
  261.       WHILE ptr <> MakeForest.FileForestEnd DO
  262.         IF NOT ptr^.library THEN
  263.           IF Strings.Pos (ptr^.filename, '.MOD', 0, c) THEN
  264.             WriteFileDependency (ptr, '.LNK');
  265.           ELSE
  266.             WriteFileDependency (ptr, '.SYM');
  267.           END; (* IF *)
  268.         END; (* IF *)
  269.         ptr     := ptr^.next;
  270.       END; (* WHILE *)
  271.     ELSE
  272.       InOut.WriteString ('Error opening MAKEFILE');
  273.       InOut.WriteLn;
  274.     END; (* IF *)
  275.     CloseOutput;
  276.   END WriteMakefile;
  277.  
  278. VAR
  279.   modulename,
  280.   filename : ARRAY [0 .. 132] OF CHAR;
  281.  
  282. BEGIN
  283.   IF CommandLine.NumberOfArguments() < 1 THEN  
  284.     InOut.WriteString ("Usage:   MAKEMAKE main-module-modulename");
  285.     InOut.WriteLn;
  286.   ELSE
  287.     CommandLine.GetArgument (1, filename);
  288.     MakeParse.ParseModule (filename, MakeParse.main, filename);
  289.     WriteMakefile;
  290.   END; (* IF *)
  291. END MakeMake.
  292.